package com.xunk.equipment.service.mandun.service.impl;

import com.alibaba.fastjson.JSON;
import com.xunk.common.core.constant.HttpStatus;
import com.xunk.common.core.constant.MessageNotifyConstants;
import com.xunk.common.core.enums.DeviceEnum;
import com.xunk.common.core.utils.BeanUtil;
import com.xunk.common.core.utils.StringUtils;
import com.xunk.common.core.utils.serialization.JsonSerializer;
import com.xunk.common.redis.service.RedisService;
import com.xunk.equipment.api.domain.MessageNotificationDO;
import com.xunk.equipment.domain.EquipmentDO;
import com.xunk.equipment.domain.HomeDO;
import com.xunk.equipment.mapper.EquipmentMapper;
import com.xunk.equipment.mapper.HomeMapper;
import com.xunk.equipment.service.BaseService;
import com.xunk.equipment.service.IEquipmentNotifyService;
import com.xunk.equipment.service.mandun.constant.MandunConstant;
import com.xunk.equipment.service.mandun.vo.MandunAlarmContent;
import com.xunk.equipment.service.mandun.vo.MandunEventContent;
import com.xunk.equipment.service.mandun.vo.MandunPush;
import com.xunk.equipment.service.mandun.vo.MandunRealTimeStatus;
import com.xunk.equipment.websocket.WebsocketManager;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @ProjectName: xunk
 * @Package: com.xunk.equipment.service.mandun.service.impl
 * @ClassName: MandunAirSwitchNotifyServiceImpl
 * @Author: luanzhiwei
 * @Description: 曼顿接收推送消息
 * @Date: 2021/4/2 14:39
 * @Version: 1.0
 */
@Service
@Slf4j
public class MandunAirSwitchNotifyServiceImpl implements IEquipmentNotifyService {

    @Autowired
    private RedisService redisService;

    @Autowired
    HomeMapper homeMapper;
    @Autowired
    private EquipmentMapper equipmentMapper;

    @Autowired
    BaseService baseService;

    public static final String alarmMessage = "尊敬的用户，您的家庭\"{}\"中\"{}\"智能空开因检测到漏电而导致自动关闭空开，请及时寻求专业人员进行检修~";

    @Override
    public void equipmentNotify(String data) {
        MandunPush deserialize = JsonSerializer.deserialize(data, MandunPush.class);
        String type = deserialize.getType();
        log.info("曼顿push-content：{}", deserialize.getContent());
        switch (type) {
            case "receiveAlarm":
                this.receiveAlarm(deserialize);
                break;
            case "receiveRealTime":
                this.receiveRealTime(deserialize);
                break;
            case "receiveEvent":
                this.receiveEvent(deserialize);
                break;
            default:
                log.info("错误的推送类型");
                break;
        }
    }


    /**
     * 接收告警推送
     *
     * @param mandunPush
     * @return
     */
    private void receiveAlarm(MandunPush mandunPush) {
//

        /*{
         "mac":"98CC4D0000",
         "dateTime":"2019-11-12 17:01:32",
         "typeNumber":11,
         "autoid":1,
         "node":"总路",
         "addr":0,
         "type":"警告",
         "info":"打火报警",
         "valueDescribe":"{\"unit\":\"0.1mA\",\"elecType\":3,\"threshold\":300,\"value\":1000}",
         "status":1
         }*/
        MandunAlarmContent alarmContent = JsonSerializer.deserialize(mandunPush.getContent(), MandunAlarmContent.class);
        CompletableFuture.runAsync(() -> {
            final String deviceSn = alarmContent.getMac();
            //查询设备属性
            EquipmentDO equipmentInfo = baseService.getEquipmentInfo(deviceSn);
            final Long deptId = equipmentInfo.getDeptId();
            //查询家庭信息
            HomeDO home = homeMapper.findMasterHomeByDeptId(equipmentInfo.getDeptId());
            MessageNotificationDO messageN = new MessageNotificationDO();
            messageN.setDeptId(deptId);
            messageN.setType(MessageNotifyConstants.DEVICE_TYPE);
            messageN.setCreateTime(new Date());
            messageN.setTriggerId(deviceSn);
            // 设备检测报警
            messageN.setTitle("设备告警通知");
            messageN.setContent(StringUtils.format(alarmMessage, home.getHomeName(), alarmContent.getNode()));

            // 查找当前home对应的user
            List<Long> userIds = homeMapper.listUserIdsByDeptId(deptId);

            // 发送告警或者故障消息
            List<MessageNotificationDO> list = userIds.stream().map(userId -> {
                MessageNotificationDO m = new MessageNotificationDO();
                BeanUtil.copy(messageN, m);
                m.setUserId(userId);
                return m;
            }).collect(Collectors.toList());
            baseService.insertMessageNotifications(list);
        });

    }

    /**
     * 接收曼顿状态实时变更消息
     * 单条addr推送
     *
     * @param mandunPush
     * @return
     */
    private void receiveRealTime(MandunPush mandunPush) {
        MandunRealTimeStatus realTimeStatus = JsonSerializer.deserialize(mandunPush.getContent(), MandunRealTimeStatus.class);
        final String mac = realTimeStatus.getMac();
        String key = MandunConstant.MANDUN_REAL_TIME_KEY + mac;
        //更新 MandunConstant.MANDUN_REAL_TIME_KEY
        final String cacheObject = redisService.getCacheObject(key);
        final List<MandunRealTimeStatus> cacheList = JsonSerializer.deserializeArray(cacheObject, MandunRealTimeStatus.class);
        List<MandunRealTimeStatus> oldStatus;
        if (!CollectionUtils.isEmpty(cacheList)) {
            oldStatus = JsonSerializer.deserializeArray(JsonSerializer.serialize(cacheList), MandunRealTimeStatus.class);
            ListIterator<MandunRealTimeStatus> iterator = oldStatus.listIterator();
            while (iterator.hasNext()) {
                final MandunRealTimeStatus next = iterator.next();
                if (next.getAddr().equals(realTimeStatus.getAddr())) {
                    realTimeStatus.setTitle(next.getTitle());
                    iterator.remove();
                    iterator.add(realTimeStatus);
                }
            }
        } else {
            oldStatus = Collections.singletonList(realTimeStatus);
        }
        redisService.setCacheObject(key, JsonSerializer.serialize(oldStatus), 1, TimeUnit.DAYS);

        try {
            log.info("曼顿空开{}状态变更开始推送", mac);
            // 推送APP实时数据
            Map<String, Object> m = new HashMap<>();
            m.put("code", HttpStatus.SUCCESS);
            m.put("msg", "设备信息");
            // 设备控制类型 为3
            m.put("type", 3);
            Map<String, Object> unit = new HashMap<>();
            unit.put("online", realTimeStatus.ifOnline());
            unit.put("mac", mac);
            unit.put("addr", realTimeStatus.getAddr());
            unit.put("title", realTimeStatus.getTitle());
            unit.put("mainLine", realTimeStatus.getMainLine());

            Map<String, Object> properties = new HashMap<>();
            properties.put("oc", realTimeStatus.isOc());

            unit.put("deviceSn", mac);
            unit.put("properties", properties);
            unit.put("deviceType", DeviceEnum.AIR_SWITCH.getDeviceType());
            m.put("data", unit);

            EquipmentDO equipmentInfo = baseService.getEquipmentInfo(mac);
            List<Long> userIds = homeMapper.listUserIdsByDeptId(equipmentInfo.getDeptId());
            String s = JSON.toJSONString(m);
            userIds.forEach(userId -> WebsocketManager.appointSending(String.valueOf(userId), s));
        } catch (Exception e) {
            log.error("发送曼顿空开实时数据到APP异常", e);
        }

    }

    /**
     * 接收曼顿事件通知消息
     *
     * @param mandunPush
     * @return
     */
    private void receiveEvent(MandunPush mandunPush) {
        MandunEventContent eventContent = JsonSerializer.deserialize(mandunPush.getContent(), MandunEventContent.class);
        long online = 0L;
        if (eventContent.getEventType().equals("DEV_ONLINE")) {
            online = 1L;
        }
        equipmentMapper.updateEquipmentOnline(eventContent.getMac(), online);
    }
}
